﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wedo.Domain.Models;  
using EFCachingProvider.Caching;
using EFCachingProvider;
using System.Web.Caching;
using System.Data.Entity;
using Wedo.Mvc.Utility;

namespace Wedo.Recognition.Repository
{

    public class UserRepository : CachedRepository<UserInfo>, IUserRepository
    {
        #region 一般方法


        public UserRepository(DbContext dbContext):base(dbContext)
        {
        }

        public IEnumerable<UserInfo> FilterByRole(string role)
        {
            if (role.IsNotNullOrWhiteSpace())
                throw new ArgumentNullException("role");

            return All().Where(m => m.Roles.Any(s => s.Id == role));

        }

        public void AddUserWithRole(UserInfo user, List<string> roles)
        {
            if (roles == null || roles.Count == 0)
                throw new ArgumentNullException("roles");

            user.Roles = GetRolesFormId(roles);

            _dbSet.Add(user);
            _dbContext.SaveChanges();
        }

        public void UpdateUserWithRole(UserInfo user, List<string> roles)
        {
            if (roles == null || roles.Count == 0)
                throw new ArgumentNullException("roles");
            var model = _dbSet.Find(user.Id);
            _dbContext.Entry(model).CurrentValues.SetValues(user);
            model.Modified = DateTime.Now;
            model.Roles.Clear();
            model.Roles.AddRange(GetRolesFormId(roles));

            _dbContext.SaveChanges();
        }

        public UserInfo GetByName(string name)
        {
            name = name.Trim().ToLower();
            return Find(m => m.Name.ToLower() == name);
        }

        public bool Login(string userName, string password)
        {
            password = StringHelper.HashPassword(password);
            return CachedAll().Any(m => m.Name == userName && m.Password == password);
        }

        public bool ChangePassword(string userName, string oldpass, string newPass)
        {
            if (newPass.IsNullOrWhiteSpace())
                throw new Exception("新密码不能为空！");

            var model = GetByName(userName);
            if (model == null)
            {
                throw new Exception("没有此用户！");
            }
            oldpass = StringHelper.HashPassword(oldpass);

            if (model.Password.Equals(oldpass))
            {
                model.Password = StringHelper.HashPassword(newPass);
            }
            return true;
        }

        public CurrentUser GetCurrentUser(string name)
        {
            var model = GetByName(name);
            if (model != null)
            {
                return new CurrentUser(model.Name, model.StaffNameEN
                    , model.Roles.Select(m => m.Id).ToArray());
            }
            return null;
        }

        /// <summary>
        /// 转换类型
        /// </summary>
        /// <param name="roles"></param>
        /// <returns></returns>
        private List<Role> GetRolesFormId(List<string> roles)
        {
            return _dbContext.Set<Role>()
                .Where(m => roles.Any(s => s == m.Id)).ToList();
        }

        #endregion

        /// <summary>
        /// 是否有权限
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="actionName"></param>
        /// <param name="roles"></param>
        /// <returns></returns>
        public bool IsInResource(string controller, string actionName, string[] roles)
        {
            if (controller.IsNullOrWhiteSpace() || actionName.IsNullOrWhiteSpace())
            {
                return false;
            }

            //如果不在资源中不做限制
            if (GetResource().Any(m => m.Action == actionName && m.Controller == controller)==false)
                return true;

            controller = controller.ToLower();
            actionName = actionName.ToLower();

            //if (controller == "home" || controller == "account" 
            //    || controller == "userinfo")
            //    return true;

            if (roles != null && roles.Length > 0)
            {
                return GetRoleResource(roles).Any(m => m.Controller.ToLower() == controller && m.Action.ToLower() == actionName);
            }

            return false;
        }

        /// <summary>
        /// 根据角色获取资源
        /// </summary>
        /// <param name="roles"></param>
        /// <returns></returns>
        public List<Resource> GetRoleResource(string[] roles)
        {
            var res = GetResource();
            var list = new List<Resource>();
            var rr = GetResourceRoles().Where(m => roles.Any(s => s == m.Role_Id));
            foreach (var item in res)
            {
                if (rr.Any(s => s.Resource_Id == item.Id)) {
                    list.Add(item);
                }
            }
            return list;
        }

        private List<RoleUserInfoes> GetRoleUserInfo()
        {
            string rKey = typeof(RoleUserInfoes).Name;
            object data = null;
            if (_Cache.GetItem(rKey, out data) == false)
            {
                if (data == null)
                {
                    string sql = "select * from RoleUserInfoes ";

                    data = _dbContext.Database.SqlQuery<ResourceRoles>(sql).ToList();
                     _Cache.PutItem(rKey, data,
                        new string[] { rKey }, Cache.NoSlidingExpiration, Cache.NoAbsoluteExpiration);
                }
            }
            return data as List<RoleUserInfoes>;
        }

        private List<ResourceRoles> GetResourceRoles()
        {
            string rKey = typeof(ResourceRoles).Name;
            object data = null;
            if (_Cache.GetItem(rKey, out data) == false)
            {
                if (data == null)
                {
                    string sql = "select * from ResourceRoles ";

                    data = _dbContext.Database.SqlQuery<ResourceRoles>(sql).ToList();
                    _Cache.PutItem( rKey, data,
                        new string[] { rKey }, Cache.NoSlidingExpiration, Cache.NoAbsoluteExpiration);
                }
            }
            return data as List<ResourceRoles>;

        }

        private List<Resource> GetResource()
        {
            string rKey = typeof(Resource).Name;
            object data = null;
            if (_Cache.GetItem(rKey, out data) == false)
            {
                if (data == null)
                {
                    data = _dbContext.Set<Resource>().ToList();
                    _Cache.PutItem( rKey, data,
                        new string[] { rKey }, Cache.NoSlidingExpiration, Cache.NoAbsoluteExpiration);
                }
            }
            return data as List<Resource>;
        }
    }
}
